﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.IsolatedStorage;
using System.Xml.Serialization;

namespace Chenglin.WPMyStep
{
    [XmlRoot("record")]
    public class StepRecord
    {
        /// <summary>
        /// The date and time when the steps are recorded.
        /// </summary>
        [XmlAttribute("time")]
        public DateTime DateTime { get; set; }

        /// <summary>
        /// Get an array of locations.
        /// </summary>
        [XmlElement("loc")]
        public LocationWithTimestamp[] Locations { get; set; }

        private static XmlSerializer s_serializer;

        public static StepRecord ReadFromFile(DateTime timeRecorded)
        {
            if (timeRecorded == DateTime.MinValue)
            {
                throw new ArgumentOutOfRangeException("timeRecorded");
            }

            if (s_serializer == null)
            {
                s_serializer = new XmlSerializer(typeof(StepRecord));
            }

            string fileName = ToFileName(timeRecorded);
            var storageFile = IsolatedStorageFile.GetUserStoreForApplication();
            if (storageFile.FileExists(fileName))
            {
                using (IsolatedStorageFileStream fileStream = storageFile.OpenFile(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    return s_serializer.Deserialize(fileStream) as StepRecord;
                }
            }
            return null;
        }

        /// <summary>
        /// Get all saved files.
        /// </summary>
        public static DateTime[] GetRecordFiles()
        {
            var storageFile = IsolatedStorageFile.GetUserStoreForApplication();
            var fileNames = storageFile.GetFileNames("*.xml");
            if (fileNames != null)
            {
                List<DateTime> list = new List<DateTime>(fileNames.Length);
                foreach (string fileName in fileNames)
                {
                    DateTime d = FromFileName(fileName);
                    if (d != DateTime.MinValue)
                    {
                        list.Add(d);
                    }
                }

                return list.ToArray();
            }

            return new DateTime[0];
        }

        /// <summary>
        /// Delete the specified file from the storage.
        /// </summary>
        public static void DeleteRecordFile(string fileName)
        {
            if (string.IsNullOrEmpty(fileName))
            {
                throw new ArgumentNullException("fileName");
            }

            var storageFile = IsolatedStorageFile.GetUserStoreForApplication();
            if (storageFile.FileExists(fileName))
            {
                storageFile.DeleteFile(fileName);
            }
        }

        /// <summary>
        /// Save the records as a file to the storage
        /// </summary>
        public void Save()
        {
            if (Locations == null || Locations.Length == 0)
            {
                // No data to be saved.
                return;
            }

            this.DateTime = Locations[0].Time;
            string file = ToFileName(DateTime);

            if (s_serializer == null)
            {
                s_serializer = new XmlSerializer(typeof(StepRecord));
            }

            var storageFile = IsolatedStorageFile.GetUserStoreForApplication();
            using (IsolatedStorageFileStream fileStream = storageFile.OpenFile(file, FileMode.Create, FileAccess.Write))
            {
                s_serializer.Serialize(fileStream, this);
            }
        }

        private const string FileNameFormat = "yyyyMMdd-HHmmss";
        private static DateTime FromFileName(string fileName)
        {
            if (string.IsNullOrEmpty(fileName))
            {
                throw new ArgumentNullException("fileName");
            }

            DateTime time;
            fileName = Path.GetFileNameWithoutExtension(fileName);
            if (!DateTime.TryParseExact(fileName, FileNameFormat, null, System.Globalization.DateTimeStyles.AssumeLocal, out time))
            {
                time = DateTime.MinValue;
            }
            return time;
        }

        private static string ToFileName(DateTime dt)
        {
            return string.Format("{0:yyyyMMdd-HHmmss}.xml", dt);
        }
    }
}
